//
//  MBProgressHUD+YSHUDManager.m
//  YSKitDemo
//
//  Created by Kyson on 2018/12/13.
//  Copyright © 2018 YangShen. All rights reserved.
//

#import "MBProgressHUD+YSHUDManager.h"

static CGFloat const kDefaultDelayTime = 1.2;

@implementation MBProgressHUD (YSHUDManager)

#pragma mark - 隐藏
+ (void)hideForView:(UIView *)view {
    view = view ?: [self p_ys_getKeyWindow];
    [MBProgressHUD hideHUDForView:view animated:YES];
}

+ (void)hide {
    [self hideForView:nil];
}

#pragma mark - 菊花
+ (void)show {
    [self p_ys_createHUDWithTitle:nil inView:nil];
}

+ (void)showAfterDelay:(NSTimeInterval)delay {
    MBProgressHUD *hud = [self p_ys_createHUDWithTitle:nil inView:nil];
    [hud hideAnimated:YES afterDelay:delay];
}

+ (void)showInView:(UIView *)view {
    [self p_ys_createHUDWithTitle:nil inView:view];
}

+ (void)showInView:(UIView *)view afterDelay:(NSTimeInterval)delay {
    [self showWithTitle:nil detail:nil inView:view afterDelay:delay];
}

+ (void)showWithTitle:(NSString *)title detail:(NSString *)detail {
    [self showWithTitle:title detail:nil inView:nil];
}

+ (void)showWithTitle:(NSString *)title detail:(NSString *)detail afterDelay:(NSTimeInterval)delay {
    [self showWithTitle:title detail:detail inView:nil afterDelay:delay];
}

+ (void)showWithTitle:(NSString *)title detail:(NSString *)detail inView:(UIView *)view {
    [self showWithTitle:title detail:detail inView:view afterDelay:0];
}

+ (void)showWithTitle:(NSString *)title detail:(NSString *)detail inView:(UIView *)view afterDelay:(NSTimeInterval)delay {
    [self showWithTitle:title detail:detail inView:view afterDelay:delay configHUD:nil];
}

+ (void)showWithTitle:(NSString *)title detail:(NSString *)detail inView:(UIView *)view afterDelay:(NSTimeInterval)delay configHUD:(YSCurrentHUD)configHUD {
    MBProgressHUD *hud = [self p_ys_createHUDWithTitle:title inView:view];
    
    !configHUD ?: configHUD(hud);
    
    if (detail) {
        hud.detailsLabel.text = detail;
    }
    
    if (delay > 0) {
        [hud hideAnimated:YES afterDelay:delay];
    }
}

#pragma mark - 提示: 文字+详情
+ (void)showTip:(NSString *)tip {
    [self showTip:tip position:YSHUDPositionCenter];
}

+ (void)showTip:(NSString *)tip position:(YSHUDPosition)position {
    [self showTip:tip position:position afterDelay:kDefaultDelayTime];
}

+ (void)showTip:(NSString *)tip position:(YSHUDPosition)position afterDelay:(NSTimeInterval)delay {
    [self showTip:tip detail:nil position:position afterDelay:delay];
}

+ (void)showTip:(NSString *)tip detail:(NSString *)detail position:(YSHUDPosition)position afterDelay:(NSTimeInterval)delay {
    [self showTip:tip detail:detail position:position afterDelay:delay configHUD:nil];
}

+ (void)showTip:(NSString *)tip detail:(NSString *)detail position:(YSHUDPosition)position afterDelay:(NSTimeInterval)delay configHUD:(YSCurrentHUD)configHUD {
    MBProgressHUD *hud = [self p_ys_createHUDWithTitle:tip inView:nil];
    hud.mode = MBProgressHUDModeText;
    hud.margin = 12;
    hud.hudPosition(position);
    
    !configHUD ?: configHUD(hud);
    
    if (detail) {
        hud.detailsLabel.text = detail;
    }
    
    if (delay > 0) {
        [hud hideAnimated:YES afterDelay:delay];
    }
}

#pragma mark - 图片
+ (void)showImage:(UIImage *)image message:(NSString *)message {
    [self showImage:image message:message afterDelay:0];
}

+ (void)showImage:(UIImage *)image message:(NSString *)message afterDelay:(NSTimeInterval)delay {
    [self showImage:image message:message afterDelay:delay configHUD:nil];
}

+ (void)showImage:(UIImage *)image message:(NSString *)message afterDelay:(NSTimeInterval)delay configHUD:(YSCurrentHUD)configHUD {
    MBProgressHUD *hud = [self p_ys_createHUDWithTitle:message inView:nil];
    hud.mode = MBProgressHUDModeCustomView;
    hud.customView = [[UIImageView alloc] initWithImage:image];
    
    !configHUD ?: configHUD(hud);
    
    if (delay > 0) {
        [hud hideAnimated:YES afterDelay:delay];
    }
}

+ (void)showImages:(NSArray<UIImage *> *)images message:(NSString *)message {
    [self showImages:images showSize:CGSizeZero message:message];
}

+ (void)showImages:(NSArray<UIImage *> *)images message:(NSString *)message afterDelay:(NSTimeInterval)delay {
    [self showImages:images showSize:CGSizeZero message:message afterDelay:delay];
}

+ (void)showImages:(NSArray<UIImage *> *)images showSize:(CGSize)size message:(NSString *)message {
    [self showImages:images showSize:size message:message afterDelay:0];
}

+ (void)showImages:(NSArray<UIImage *> *)images showSize:(CGSize)size message:(NSString *)message afterDelay:(NSTimeInterval)delay {
    [self showImages:images showSize:size message:message afterDelay:delay configHUD:nil];
}

+ (void)showImages:(NSArray<UIImage *> *)images showSize:(CGSize)size message:(NSString *)message afterDelay:(NSTimeInterval)delay configHUD:(YSCurrentHUD)configHUD {
    MBProgressHUD *hud = [self p_ys_createHUDWithTitle:message inView:nil];
    hud.mode = MBProgressHUDModeCustomView;
    
    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.animationImages = images;
    imageView.animationDuration = images.count * 0.1;
    imageView.animationRepeatCount = HUGE_VALF;
    [imageView startAnimating];
    
    if (!CGSizeEqualToSize(size, CGSizeZero)) {
        NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:size.width];
        NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:size.height];
        [imageView addConstraint:width];
        [imageView addConstraint:height];
    }
    
    hud.customView = imageView;
    if (!message || message.length == 0) {
        hud.margin = 0;
    }
    
    !configHUD ?: configHUD(hud);
    
    if (delay > 0) {
        [hud hideAnimated:YES afterDelay:delay];
    }
}

+ (void)showGif:(UIImage *)gifImage message:(NSString *)message {
    [self showGif:gifImage message:message afterDelay:0];
}

+ (void)showGif:(UIImage *)gifImage message:(NSString *)message afterDelay:(NSTimeInterval)delay {
    [self showGif:gifImage message:message afterDelay:delay configHUD:nil];
}

+ (void)showGif:(UIImage *)gifImage message:(NSString *)message afterDelay:(NSTimeInterval)delay configHUD:(YSCurrentHUD)configHUD {
    MBProgressHUD *hud = [self p_ys_createHUDWithTitle:message inView:nil];
    hud.mode = MBProgressHUDModeCustomView;
    
    UIImageView *gifImageView = [[UIImageView alloc] initWithImage:gifImage];
    hud.customView = gifImageView;
    
    !configHUD ?: configHUD(hud);
    
    if (delay > 0) {
        [hud hideAnimated:YES afterDelay:delay];
    }
}

#pragma mark - private method
+ (MBProgressHUD *)p_ys_createHUDWithTitle:(NSString *)title inView:(UIView *)view {
    view = view ?: [self p_ys_getKeyWindow];
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
    
    // 隐藏时候从父控件中移除
    hud.removeFromSuperViewOnHide = YES;
    // 支持多行
    hud.label.numberOfLines = 0;
    // 文字
    hud.label.text = title;
    
    // 设置默认风格
    if (YSDefaultHudStyle == 1) {
        hud.hudContentStyle(YSHUDContentStyleBlack);
    } else if (YSDefaultHudStyle == 2) {
        hud.hudContentStyle(YSHUDContentStyleCustom);
    }
    
    return hud;
}

#pragma mark - getter
/// 内容风格
- (MBProgressHUD *(^)(YSHUDContentStyle))hudContentStyle {
    return ^(YSHUDContentStyle hudContentStyle) {
        
        switch (hudContentStyle) {
            case YSHUDContentStyleBlack: {
                self.contentColor = [UIColor whiteColor];
                self.bezelView.backgroundColor = [UIColor blackColor];
                self.bezelView.style = MBProgressHUDBackgroundStyleBlur;
            }
                break;
            case YSHUDContentStyleCustom: {
                self.contentColor = YSCustomHudStyleContentColor;
                self.bezelView.backgroundColor = YSCustomHudStyleBackgrandColor;
                self.bezelView.style = MBProgressHUDBackgroundStyleBlur;
            }
                break;
            default: {
                self.contentColor = [UIColor blackColor];
                self.bezelView.backgroundColor = [UIColor colorWithWhite:0.902 alpha:1.000];
                self.bezelView.style = MBProgressHUDBackgroundStyleBlur;
            }
                break;
        }
        return self;
    };
}

/// 蒙层背景色
- (MBProgressHUD *(^)(UIColor *))hudBackgroundColor {
    return ^(UIColor *hudBackgroundColor) {
        self.backgroundView.color = hudBackgroundColor;
        return self;
    };
}

/// 内容背景色
- (MBProgressHUD *(^)(UIColor *))bezelBackgroundColor {
    return ^(UIColor *bezelViewColor){
        self.bezelView.backgroundColor = bezelViewColor;
        return self;
    };
}

/// 显示位置
- (MBProgressHUD *(^)(YSHUDPosition))hudPosition {
    return ^(YSHUDPosition hudPosition){
        
        switch (hudPosition) {
            case YSHUDPositionTop: {
                self.offset = CGPointMake(0.f, -MBProgressMaxOffset);
            }
                break;
            case YSHUDPositionBottom: {
                self.offset = CGPointMake(0.f, MBProgressMaxOffset);
            }
                break;
            default: {
                self.offset = CGPointMake(0.f, 0.f);
            }
                break;
        }
        return self;
    };
}

/// 进度条风格
- (MBProgressHUD *(^)(YSHUDProgressStyle))hudProgressStyle {
    return ^(YSHUDProgressStyle hudProgressStyle) {
        
        switch (hudProgressStyle) {
            case YSHUDProgressStyleDeterminateHorizontalBar: {
                self.mode = MBProgressHUDModeDeterminateHorizontalBar;
            }
                break;
            case YSHUDProgressStyleAnnularDeterminate: {
                self.mode = MBProgressHUDModeAnnularDeterminate;
            }
                break;
            case YSHUDProgressStyleCancelationDeterminate: {
                self.mode = MBProgressHUDModeDeterminate;
            }
                break;
            default: {
                self.mode = MBProgressHUDModeDeterminate;
            }
                break;
        }
        return self;
    };
}

/// 标题
- (MBProgressHUD *(^)(NSString *))title {
    return ^(NSString *title) {
        self.label.text = title;
        return self;
    };
}

/// 详情
- (MBProgressHUD *(^)(NSString *))details {
    return ^(NSString *details) {
        self.detailsLabel.text = details;
        return self;
    };
}

/// 自定义图片名
- (MBProgressHUD *(^)(NSString *))customIcon {
    return ^(NSString *customIcon) {
        self.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:customIcon]];
        return self;
    };
}

/// 标题颜色
- (MBProgressHUD *(^)(UIColor *))titleColor {
    return ^(UIColor *titleColor){
        self.label.textColor = titleColor;
        self.detailsLabel.textColor = titleColor;
        return self;
    };
}

/// 进度条颜色
- (MBProgressHUD *(^)(UIColor *))progressColor {
    return ^(UIColor *progressColor) {
        UIColor *titleColor = self.label.textColor;
        self.contentColor = progressColor;
        self.label.textColor = titleColor;
        self.detailsLabel.textColor = titleColor;
        return self;
    };
}

/// 进度条、标题颜色
- (MBProgressHUD *(^)(UIColor *))allContentColors {
    return ^(UIColor *allContentColors) {
        self.contentColor = allContentColors;
        return self;
    };
}

#pragma mark - help method

/// 获取当前 keyWindow
+ (UIView *)p_ys_getKeyWindow {
    return (UIView *)[UIApplication sharedApplication].delegate.window;
}

/// 获取当前屏幕显示的viewcontroller
+ (UIViewController *)p_ys_getCurrentUIVC {
    UIViewController *superVC = [[self class] p_ys_getCurrentWindowVC];
    if ([superVC isKindOfClass:[UITabBarController class]]) {
        UIViewController *tabSelectVC = ((UITabBarController*)superVC).selectedViewController;
        if ([tabSelectVC isKindOfClass:[UINavigationController class]]) {
            return ((UINavigationController*)tabSelectVC).viewControllers.lastObject;
        }
        return tabSelectVC;
    }else
        if ([superVC isKindOfClass:[UINavigationController class]]) {
            return ((UINavigationController*)superVC).viewControllers.lastObject;
        }
    return superVC;
}

+ (UIViewController *)p_ys_getCurrentWindowVC {
    UIViewController *result = nil;
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    if (window.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for (UIWindow * tempWindow in windows) {
            if (tempWindow.windowLevel == UIWindowLevelNormal) {
                window = tempWindow;
                break;
            }
        }
    }
    UIView *frontView = [[window subviews] objectAtIndex:0];
    id nextResponder = [frontView nextResponder];
    if ([nextResponder isKindOfClass:[UIViewController class]]) {
        result = nextResponder;
    } else {
        result = window.rootViewController;
    }
    return  result;
}

#pragma mark - Data -> Gif
+ (UIImage *)imageGIFWithData:(NSData *)data {
    if (!data) {
        return nil;
    }
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    size_t count = CGImageSourceGetCount(source);
    UIImage *animatedImage;
    if (count <= 1) {
        animatedImage = [[UIImage alloc] initWithData:data];
    }
    else {
        NSMutableArray *images = [NSMutableArray array];
        NSTimeInterval duration = 0.0f;
        for (size_t i = 0; i < count; i++) {
            CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
            if (!image) {
                continue;
            }
            duration += [self p_frameDurationAtIndex:i source:source];
            [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
            CGImageRelease(image);
        }
        if (!duration) {
            duration = (1.0f / 10.0f) * count;
        }
        animatedImage = [UIImage animatedImageWithImages:images duration:duration];
    }
    CFRelease(source);
    return animatedImage;
}

+ (float)p_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
    float frameDuration = 0.1f;
    CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
    NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
    NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
    NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
    if (delayTimeUnclampedProp) {
        frameDuration = [delayTimeUnclampedProp floatValue];
    }
    else {
        NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
        if (delayTimeProp) {
            frameDuration = [delayTimeProp floatValue];
        }
    }
    if (frameDuration < 0.011f) {
        frameDuration = 0.100f;
    }
    CFRelease(cfFrameProperties);
    return frameDuration;
}

@end
